package com.cloudbroker.bcs.csvc.base.facade.service;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;

import com.cloudbroker.bcs.common.context.RuntimeContext;
import com.cloudbroker.bcs.common.util.ValueUtil;
import com.cloudbroker.bcs.csvc.base.api.constants.HSBCCSFields;
import com.cloudbroker.bcs.csvc.base.api.service.HSBCCSService;
import com.cloudbroker.bcs.csvc.base.common.exception.HSBCCSException;
import com.cloudbroker.bcs.csvc.base.common.util.HSBCCSServiceHelper;

public abstract class HSBCCSServiceFacade<T> implements HSBCCSService {
    
    @SuppressWarnings("unchecked")
    protected Map<String, Object> operate(OperationHandler<T> operationHandler, Map<String, Object> param , String implType) {
        Logger logger = getLogger();
        
        Map<String, Object> result = new HashMap<String, Object>();
        // 取实现类型，如果没有就按默认的
        implType = ValueUtil.getString(param.remove(implType));
        if (StringUtils.isBlank(implType)) {
            implType = getDefaultImplType();
        }
        try {
            // 按实现类型获取bean
            T implService = (T) RuntimeContext.getBean(implType);
            if (null != implService) {
                // 实现bean存在即调用
                operationHandler.callImpl(implService, param, result);
            } else {
                // 实现bean不存在则报告错误
                // 一般不会出现，但通过工厂类获取有可能
                HSBCCSServiceHelper.markNoSuchImpl(result);
            }
        } catch (NoSuchBeanDefinitionException e) {
            // 实现bean不存在则报告错误
            logger.error("no such implType: " + implType, e);
            HSBCCSServiceHelper.markNoSuchImpl(result);
        } catch (HSBCCSException e) {
            logger.error("Operation failed.", e);
            HSBCCSServiceHelper.markError(result, e);
        } catch (Exception e) {
            logger.error("Operation failed.", e);
            HSBCCSServiceHelper.markCommonError(result);
        }
        return result;
    }
    
    protected interface OperationHandler<T> {
        
        public void callImpl(T implService, Map<String, Object> param, Map<String, Object> result);
        
    }
    
    protected abstract Logger getLogger();
    
    protected abstract String getDefaultImplType();
    
}
